﻿#region

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;

#endregion

[assembly: WebResource("ControlToolkitExtended.BreadCrumb.rightarrow.png", "image/gif")]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.icon_arrow_down.gif", "image/gif")]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.icon_arrow_right.gif", "image/gif")]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.arrow-left.gif", "image/gif")]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.gradient.png", "image/gif")]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.BreadCrumb.css", "text/css", PerformSubstitution = true)]
[assembly: WebResource("ControlToolkitExtended.BreadCrumb.BreadCrumbBehavior.js", "text/javascript")]

namespace AjaxControlToolkit
{
    [Designer("ControlToolkitExtended.BreadCrumpDesigner, AjaxControlToolkit")]
    [TargetControlType(typeof (LinkButton))]
    [RequiredScript(typeof (CommonExtended), 0)]
    [RequiredScript(typeof (AnimationExtender), 1)]
    [ClientCssResource("ControlToolkitExtended.BreadCrumb.BreadCrumb.css")]
    [ClientScriptResource("AjaxControlToolkit.BreadCrumbBehavior", "ControlToolkitExtended.BreadCrumb.BreadCrumbBehavior.js", LoadOrder = 2)]
    public class BreadCrumbExtender : ExtenderControlBase
    {
        private static JavaScriptSerializer _javaScriptSerializer = new JavaScriptSerializer();
        
        public BreadCrumbExtender()
        {
            EnableClientState = true;
            ClientStateValuesLoaded += BreadCrumbExtender_ClientStateValuesLoaded;
        }

        void BreadCrumbExtender_ClientStateValuesLoaded(object sender, EventArgs e)
        {
            string s = ClientState;
            if (!string.IsNullOrEmpty(s))
            {
                var state = _javaScriptSerializer.Deserialize<Dictionary<string, object>>(s);
                foreach (string key in state.Keys)
                {
                    if (!string.IsNullOrEmpty(key) && (state[key] != null))
                    {
                        if (key == "currentPath")
                        {
                            CurrentPath = state[key].ToString();
                        }
                        else if (key == "readOnly")
                        {
                            ViewState[key] = state[key].ToString();
                        }
                    }
                }
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            LinkButton targetControl = FindControlHelper(TargetControlID) as LinkButton;
            if (targetControl != null)
            {
                List<KeyValuePair<string, string>> path = CurrentBreadCrumbPath;
                if (path.Count > 0)
                {
                    string pathName = "";
                    for (int i = 0; i < path.Count; i++)
                    {
                        pathName += path[i].Value+" > ";
                    }
                    pathName = pathName.Substring(0, pathName.Length - 3);
                    targetControl.Text = pathName;
                }
            }
        }

        [DefaultValue("")]
        [UrlProperty]
        [ExtenderControlProperty]
        [ClientPropertyName("dropArrowImageUrl")]
        public string DropArrowImageUrl
        {
            get
            {
                return (string) (ViewState["dropArrowImageUrl"] ?? String.Empty);
            }
            set
            {
                ViewState["dropArrowImageUrl"] = value;
            }
        }

        [DefaultValue(typeof (Unit), "")]
        [ExtenderControlProperty]
        [ClientPropertyName("dropArrowWidth")]
        public Unit DropArrowWidth
        {
            get
            {
                return (Unit) (ViewState["dropArrowWidth"] ?? Unit.Empty);
            }
            set
            {
                ViewState["dropArrowWidth"] = value;
            }
        }

        [DefaultValue(typeof (Color), "")]
        [ExtenderControlProperty]
        [ClientPropertyName("dropArrowBackgroundColor")]
        public Color DropArrowBackColor
        {
            get
            {
                return (Color) (ViewState["dropArrowBackColor"] ?? Color.Empty);
            }
            set
            {
                ViewState["dropArrowBackColor"] = value;
            }
        }

        /// <summary>
        ///   The web service method to be called.
        /// </summary>
        [DefaultValue("")]
        [RequiredProperty]
        [ExtenderControlProperty]
        [ClientPropertyName("serviceMethod")]
        public virtual string ServiceMethod
        {
            get
            {
                return ((string)(ViewState["serviceMethod"]??""));
            }
            set
            {
                ViewState["serviceMethod"] = value;
            }
        }

        /// <summary>
        ///   The path to the web service that the extender will pull the 
        ///   word\sentence completions from. If this is not provided, the 
        ///   service method should be a page method.
        /// </summary>
        [UrlProperty]
        [ExtenderControlProperty]
        [TypeConverter(typeof (ServicePathConverter))]
        [ClientPropertyName("servicePath")]
        public virtual string ServicePath
        {
            get
            {
                return ((string)(ViewState["servicePath"]??""));
            }
            set
            {
                ViewState["servicePath"] = value;
            }
        }

        /// <summary>
        ///   Css Class that will be used to style the completion list flyout.
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlProperty]
        [ClientPropertyName("completionListCssClass")]
        public string CompletionListCssClass
        {
            get
            {
                return ((string)(ViewState["completionListCssClass"] ?? ""));
            }
            set
            {
                ViewState["completionListCssClass"] = value;
            }
        }

        /// <summary>
        ///   Css Class that will be used to style the completion list flyout when hover.
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlProperty]
        [ClientPropertyName("completionListHoverCssClass")]
        public string CompletionListHoverCssClass
        {
            get
            {
                return (string)(ViewState["completionListHoverCssClass"]?? "");
            }
            set
            {
                ViewState["completionListHoverCssClass"] =  value;
            }
        }

        /// <summary>
        ///   Css Class that will be used to style an item in the autocomplete list.
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlProperty]
        [ClientPropertyName("completionListItemCssClass")]
        public string CompletionListItemCssClass
        {
            get
            {
                return (string)(ViewState["completionListItemCssClass"]??"");
            }
            set
            {
                ViewState["completionListItemCssClass"] =  value;
            }
        }

        /// <summary>
        ///   Css Class that will be used to style a highlighted item in the autocomplete list.
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlProperty]
        [ClientPropertyName("highlightedItemCssClass")]
        public string CompletionListHighlightedItemCssClass
        {
            get
            {
                return (string)(ViewState["completionListHighlightedItemCssClass"]?? "");
            }
            set
            {
                ViewState["completionListHighlightedItemCssClass"] = value;
            }
        }

        /// <summary>
        ///   Css Class that will be used to style a highlighted item in the autocomplete list.
        /// </summary>
        [DefaultValue("false")]
        [ExtenderControlProperty]
        [ClientPropertyName("readOnly")]
        public bool ReadOnly
        {
            get
            {
                return bool.Parse((string)(ViewState["readOnly"] ?? "false"));
            }
            set
            {
                ViewState["readOnly"] = value.ToString();
            }
        }

        [DefaultValue("false")]
        [ExtenderControlProperty]
        [ClientPropertyName("autoPostBack")]
        public bool AutoPostBackOnItemSelected
        {
            get 
            {
                return bool.Parse((string)(ViewState["autoPostBack"] ?? "false"));
            }
            set
            {
                ViewState["autoPostBack"] = value.ToString();
            }
        }

        /// <summary>
        ///   List of path (key,value)
        /// </summary>
        public List<KeyValuePair<string, string>> CurrentBreadCrumbPath
        {
            get
            {
                var result = new List<KeyValuePair<string, string>>();
                var deserialized = ViewState["currentPath"] as string[];
                if (deserialized != null)
                {
                    for (int i = 0; i < deserialized.Length; i++)
                    {
                        var p = _javaScriptSerializer.Deserialize<Pair>(deserialized[i]);
                        var pathPart = new KeyValuePair<string, string>((string) p.First,(string) p.Second);
                        result.Add(pathPart);                                                                                                 
                    }
                }
                return result;
            }
            set
            {
                var serialized = new string[value.Count];
                if (value.Count > 0)
                {
                    for (int i = 0; i < value.Count; i++)
                    {
                        serialized[i] = _javaScriptSerializer.Serialize(new Pair(value[i].Key, value[i].Value));
                    }
                }
                ViewState["currentPath"] = serialized;
            }
        }

        [DefaultValue(typeof(int), "-1")]
        [ExtenderControlProperty]
        [ClientPropertyName("minSelectableLevel")]
        public int MinSelectableLevel
        {
            get
            {
                return ViewState["minSelectableLevel"]!=null?(int)ViewState["minSelectableLevel"]:-1;
            }
            set
            {
                ViewState["minSelectableLevel"] = value;
            }
        }

        /// <summary>
        ///   Use <see cref="CurrentBreadCrumbPath"/> to set this property programmicaly
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlProperty]
        [ClientPropertyName("currentPath")]
        private string CurrentPath
        {
            get
            {
                var deserialized = ViewState["currentPath"] as string[];
                string result = "";
                if (deserialized != null)
                {
                    result = _javaScriptSerializer.Serialize(deserialized);
                }
                return result;
            }
            set
            {
                var vals = _javaScriptSerializer.Deserialize<string[]>(value);
                ViewState["currentPath"] = vals;
            }
        }

        /// <summary>
        /// Handler to attach to the client-side itemSelected event
        /// </summary>
        [DefaultValue("")]
        [ExtenderControlEvent]
        [ClientPropertyName("onItemSelected")]
        public string OnClientItemSelected
        {
            get { return GetPropertyValue("OnClientItemSelected", string.Empty); }
            set { SetPropertyValue("OnClientItemSelected", value); }
        }

        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
        {
            List<ScriptDescriptor> descriptors = null;
            IEnumerable<ScriptDescriptor> baseDescriptors =  base.GetScriptDescriptors(targetControl);
            if (baseDescriptors!=null)
            {
                descriptors = new List<ScriptDescriptor>(baseDescriptors);
                for (int i = 0; i < descriptors.Count; i++)
                {
                    if (descriptors[i] is ScriptBehaviorDescriptor)
                    {
                        ((ScriptBehaviorDescriptor)descriptors[i]).AddProperty("currentPath", CurrentPath);
                    }
                }
            }
            return descriptors;
        }

        public override void Dispose()
        {
            base.Dispose();
            GC.SuppressFinalize(this);
        }
    }
}